import logging
import re
import allure
from utils.get_keywords import GetKeywords
from utils.regex import re_match_value
from utils.send_request import send_jdbc_request
from abc import ABC, abstractmethod



class Extractor(object):
    """
    抽象提取基类
    """

    def __init__(self, case, all_vars):
        """所有的方法都需要的参数"""
        self.case = case
        self.all_vars = all_vars

    def extract(self, res=None):
        raise NotImplementedError("所有的子类必须实现extract方法")


    def log_extraction(self, extraction_type, data):
        """日志打印处理"""
        logging.info(f"4.{extraction_type}提取, 根据{data}提取数据，此时全局变量为:{self.all_vars}")

    def add_to_all_vars(self, key, value):

        if key in self.all_vars:
            logging.warning(f"提取器全局变量内的{key}已经存在，目前是替换值")

        self.all_vars[key] = value

    def eval_data(self, data_str):

        try:
            return eval(data_str) if data_str else None
        except Exception as e:
            logging.error(f"提取器使用eval的时候抛出异常，数据是{data_str}，异常是{e}")



class JsonExtractor(Extractor):

    @allure.step("4. JSON提取")
    def extract(self, res):
        if self.case["jsonExData"]:
                # 首先要把 jsonExData 的 key value 拆开
            for key, value in self.eval_data(self.case["jsonExData"]).items():
                # value = jsonpath.jsonpath(res.json(), value)[0]
                value = GetKeywords.get_keyword(res, value)
                # all[key] = value
                self.add_to_all_vars(key, value)
            # logging.info(f"4.JSON提取, 根据{self.case["jsonExData"]}提取数据，此时全局变量为:{all}")
            self.log_extraction("JSON提取", self.case["jsonExData"])


class JDBCExtractor(Extractor):

    @allure.step("4. JDBC提取")
    def extract(self):
        if self.case["sqlExData"]:
            for key, value in self.eval_data(self.case["sqlExData"]).items():
                value = send_jdbc_request(value)
                # all[key] = value
                self.add_to_all_vars(key, value)
            # logging.info(f"4.JDBC提取, 根据{case["sqlExData"]}提取数据，此时全局变量为:{all}")
            self.log_extraction("JDBC提取", self.case["sqlExData"])




class ReExtractor(Extractor):
    @allure.step("4. 正则提取")
    def extract(self, res):
        if self.case["reExData"]:
            for key, value in self.eval_data(self.case["reExData"]).items():
                v = re_match_value(str(res), value)
                # all[key] = v
                self.add_to_all_vars(key, v)
            # logging.info(f"4.正则提取, 根据{case["reExData"]}提取数据，此时全局变量为:{all}")
            self.log_extraction("正则提取", self.case["reExData"])


def perform_extractions(case, all_vars, response):
    """
    执行提取器的入口
    :param case: 测试用例
    :param all_vars: 全局变量
    :param response: 返回结果
    :return:
    """
    extractions = [
        JsonExtractor(case, all_vars),
        JDBCExtractor(case, all_vars),
        ReExtractor(case, all_vars),
    ]

    for extractor in extractions:
        try:
            if isinstance(extractor, JsonExtractor) or isinstance(extractor, ReExtractor):
                extractor.extract(response)
            elif isinstance(extractor, JDBCExtractor):
                extractor.extract()
        except Exception as e:
            logging.error(f"在执行{type(extractor).__name__}发生错误, 错误异常为{e}")












# def json_extractor(case, all, res):
#     if case["jsonExData"]:
#         with allure.step("4. JSON提取"):
#             # 首先要把 jsonExData 的 key value 拆开
#             for key, value in eval(case["jsonExData"]).items():
#                 # value = jsonpath.jsonpath(res.json(), value)[0]
#                 value = GetKeywords.get_keyword(res, value)
#
#                 all[key] = value
#             logging.info(f"4.JSON提取, 根据{case["jsonExData"]}提取数据，此时全局变量为:{all}")



# def jdbc_extractor(case, all):
#     if case["sqlExData"]:
#         with allure.step("3. JDBC提取"):
#             for key, value in eval(case["sqlExData"]).items():
#                 value = send_jdbc_request(value)
#                 all[key] = value
#             logging.info(f"4.JDBC提取, 根据{case["sqlExData"]}提取数据，此时全局变量为:{all}")




# def re_match_value(string, pattern, index = 0):
#     # matches = []
#     #
#     # for match in re.finditer(pattern, string):
#     #     matches.append(match.group())
#
#     matches = [match.group(1) for match in re.finditer(pattern, string)]
#     return matches[index]

# def re_extractor(case, all, res):
#     if case["reExData"]:
#         with allure.step("4. 正则提取"):
#             for key, value in eval(case["reExData"]).items():
#                 v = re_match_value(str(res), value)
#                 all[key] =v
#             logging.info(f"4.正则提取, 根据{case["reExData"]}提取数据，此时全局变量为:{all}")

